package com.plugin.manage.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * HTTP客户端工具类
 * 提供同步和异步的HTTP请求方法
 * 
 * @author plugin-manage
 * @since 1.0.0
 */
@Slf4j
public class HttpClientUtil {

    private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    private static final RestTemplate REST_TEMPLATE = new RestTemplate();

    /**
     * HTTP请求结果封装类
     */
    public static class HttpResult {
        private int statusCode;
        private String body;
        private Map<String, String> headers;

        public HttpResult(int statusCode, String body, Map<String, String> headers) {
            this.statusCode = statusCode;
            this.body = body;
            this.headers = headers;
        }

        public int getStatusCode() { return statusCode; }
        public String getBody() { return body; }
        public Map<String, String> headers() { return headers; }
        public boolean isSuccess() { return statusCode >= 200 && statusCode < 300; }
    }

    /**
     * GET请求 - 使用RestTemplate
     */
    public static String get(String url) {
        return get(url, null);
    }

    /**
     * GET请求 - 带请求头
     */
    public static String get(String url, Map<String, String> headers) {
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            if (headers != null) {
                headers.forEach(httpHeaders::set);
            }
            
            HttpEntity<String> entity = new HttpEntity<>(httpHeaders);
            ResponseEntity<String> response = REST_TEMPLATE.exchange(url, HttpMethod.GET, entity, String.class);
            
            log.debug("GET请求成功: {} -> {}", url, response.getStatusCode());
            return response.getBody();
        } catch (Exception e) {
            log.error("GET请求失败: {}", url, e);
            throw new RuntimeException("GET请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * POST请求 - JSON数据
     */
    public static String post(String url, String jsonBody) {
        return post(url, jsonBody, null);
    }

    /**
     * POST请求 - JSON数据带请求头
     */
    public static String post(String url, String jsonBody, Map<String, String> headers) {
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            if (headers != null) {
                headers.forEach(httpHeaders::set);
            }
            
            HttpEntity<String> entity = new HttpEntity<>(jsonBody, httpHeaders);
            ResponseEntity<String> response = REST_TEMPLATE.exchange(url, HttpMethod.POST, entity, String.class);
            
            log.debug("POST请求成功: {} -> {}", url, response.getStatusCode());
            return response.getBody();
        } catch (Exception e) {
            log.error("POST请求失败: {}", url, e);
            throw new RuntimeException("POST请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * POST请求 - 表单数据
     */
    public static String postForm(String url, MultiValueMap<String, String> formData) {
        return postForm(url, formData, null);
    }

    /**
     * POST请求 - 表单数据带请求头
     */
    public static String postForm(String url, MultiValueMap<String, String> formData, Map<String, String> headers) {
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            if (headers != null) {
                headers.forEach(httpHeaders::set);
            }
            
            HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(formData, httpHeaders);
            ResponseEntity<String> response = REST_TEMPLATE.exchange(url, HttpMethod.POST, entity, String.class);
            
            log.debug("POST表单请求成功: {} -> {}", url, response.getStatusCode());
            return response.getBody();
        } catch (Exception e) {
            log.error("POST表单请求失败: {}", url, e);
            throw new RuntimeException("POST表单请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * PUT请求
     */
    public static String put(String url, String jsonBody) {
        return put(url, jsonBody, null);
    }

    /**
     * PUT请求 - 带请求头
     */
    public static String put(String url, String jsonBody, Map<String, String> headers) {
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            if (headers != null) {
                headers.forEach(httpHeaders::set);
            }
            
            HttpEntity<String> entity = new HttpEntity<>(jsonBody, httpHeaders);
            ResponseEntity<String> response = REST_TEMPLATE.exchange(url, HttpMethod.PUT, entity, String.class);
            
            log.debug("PUT请求成功: {} -> {}", url, response.getStatusCode());
            return response.getBody();
        } catch (Exception e) {
            log.error("PUT请求失败: {}", url, e);
            throw new RuntimeException("PUT请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * DELETE请求
     */
    public static String delete(String url) {
        return delete(url, null);
    }

    /**
     * DELETE请求 - 带请求头
     */
    public static String delete(String url, Map<String, String> headers) {
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            if (headers != null) {
                headers.forEach(httpHeaders::set);
            }
            
            HttpEntity<String> entity = new HttpEntity<>(httpHeaders);
            ResponseEntity<String> response = REST_TEMPLATE.exchange(url, HttpMethod.DELETE, entity, String.class);
            
            log.debug("DELETE请求成功: {} -> {}", url, response.getStatusCode());
            return response.getBody();
        } catch (Exception e) {
            log.error("DELETE请求失败: {}", url, e);
            throw new RuntimeException("DELETE请求失败: " + e.getMessage(), e);
        }
    }

    // ==================== 使用Java 11+ HttpClient的高级方法 ====================

    /**
     * 同步GET请求 - 返回详细结果
     */
    public static HttpResult getWithDetails(String url, Map<String, String> headers) {
        try {
            HttpRequest.Builder builder = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .timeout(Duration.ofSeconds(30))
                    .GET();

            if (headers != null) {
                headers.forEach(builder::header);
            }

            HttpRequest request = builder.build();
            HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());

            Map<String, String> responseHeaders = response.headers().map().entrySet().stream()
                    .collect(java.util.stream.Collectors.toMap(
                            Map.Entry::getKey,
                            entry -> String.join(",", entry.getValue())
                    ));

            log.debug("GET请求成功: {} -> {}", url, response.statusCode());
            return new HttpResult(response.statusCode(), response.body(), responseHeaders);
        } catch (Exception e) {
            log.error("GET请求失败: {}", url, e);
            throw new RuntimeException("GET请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 同步POST请求 - 返回详细结果
     */
    public static HttpResult postWithDetails(String url, String jsonBody, Map<String, String> headers) {
        try {
            HttpRequest.Builder builder = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .timeout(Duration.ofSeconds(30))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody));

            if (headers != null) {
                headers.forEach(builder::header);
            }

            HttpRequest request = builder.build();
            HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());

            Map<String, String> responseHeaders = response.headers().map().entrySet().stream()
                    .collect(java.util.stream.Collectors.toMap(
                            Map.Entry::getKey,
                            entry -> String.join(",", entry.getValue())
                    ));

            log.debug("POST请求成功: {} -> {}", url, response.statusCode());
            return new HttpResult(response.statusCode(), response.body(), responseHeaders);
        } catch (Exception e) {
            log.error("POST请求失败: {}", url, e);
            throw new RuntimeException("POST请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 异步GET请求
     */
    public static CompletableFuture<HttpResult> getAsync(String url, Map<String, String> headers) {
        try {
            HttpRequest.Builder builder = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .timeout(Duration.ofSeconds(30))
                    .GET();

            if (headers != null) {
                headers.forEach(builder::header);
            }

            HttpRequest request = builder.build();
            
            return HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                    .thenApply(response -> {
                        Map<String, String> responseHeaders = response.headers().map().entrySet().stream()
                                .collect(java.util.stream.Collectors.toMap(
                                        Map.Entry::getKey,
                                        entry -> String.join(",", entry.getValue())
                                ));
                        log.debug("异步GET请求成功: {} -> {}", url, response.statusCode());
                        return new HttpResult(response.statusCode(), response.body(), responseHeaders);
                    })
                    .exceptionally(throwable -> {
                        log.error("异步GET请求失败: {}", url, throwable);
                        throw new RuntimeException("异步GET请求失败: " + throwable.getMessage(), throwable);
                    });
        } catch (Exception e) {
            log.error("创建异步GET请求失败: {}", url, e);
            CompletableFuture<HttpResult> future = new CompletableFuture<>();
            future.completeExceptionally(e);
            return future;
        }
    }

    /**
     * 异步POST请求
     */
    public static CompletableFuture<HttpResult> postAsync(String url, String jsonBody, Map<String, String> headers) {
        try {
            HttpRequest.Builder builder = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .timeout(Duration.ofSeconds(30))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody));

            if (headers != null) {
                headers.forEach(builder::header);
            }

            HttpRequest request = builder.build();
            
            return HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                    .thenApply(response -> {
                        Map<String, String> responseHeaders = response.headers().map().entrySet().stream()
                                .collect(java.util.stream.Collectors.toMap(
                                        Map.Entry::getKey,
                                        entry -> String.join(",", entry.getValue())
                                ));
                        log.debug("异步POST请求成功: {} -> {}", url, response.statusCode());
                        return new HttpResult(response.statusCode(), response.body(), responseHeaders);
                    })
                    .exceptionally(throwable -> {
                        log.error("异步POST请求失败: {}", url, throwable);
                        throw new RuntimeException("异步POST请求失败: " + throwable.getMessage(), throwable);
                    });
        } catch (Exception e) {
            log.error("创建异步POST请求失败: {}", url, e);
            CompletableFuture<HttpResult> future = new CompletableFuture<>();
            future.completeExceptionally(e);
            return future;
        }
    }

    /**
     * 下载文件
     */
    public static byte[] downloadFile(String url, Map<String, String> headers) {
        try {
            HttpRequest.Builder builder = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .timeout(Duration.ofMinutes(5))
                    .GET();

            if (headers != null) {
                headers.forEach(builder::header);
            }

            HttpRequest request = builder.build();
            HttpResponse<byte[]> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofByteArray());

            if (response.statusCode() >= 200 && response.statusCode() < 300) {
                log.debug("文件下载成功: {} -> {} bytes", url, response.body().length);
                return response.body();
            } else {
                throw new RuntimeException("文件下载失败，状态码: " + response.statusCode());
            }
        } catch (Exception e) {
            log.error("文件下载失败: {}", url, e);
            throw new RuntimeException("文件下载失败: " + e.getMessage(), e);
        }
    }
}
